using System;
using System.Collections.Generic;
using System.Linq;
using OpenQA.Selenium;
using YatFram.Browser.CssSelector;

namespace YatFram.Browser.Selenium
{
    public static class SeleniumConstraints
    {
        private static readonly IDictionary<Func<CssSelectors, Selector>, Func<string, By>> seleniumConstraints =
            new Dictionary<Func<CssSelectors, Selector>, Func<string, By>>
                {
                    {cs => cs.Id, By.Id},
                    {cs => cs.Class, By.ClassName},
                    {cs => cs.Name, By.Name},
                };


        public static IWebElement FindElement(this IWebDriver driver, string cssSelector)
        {
            var constraints = GetConstraints(cssSelector);
            var firstConstraint = constraints.First();
            var restOfTheConstrains = constraints.Skip(1);
            return restOfTheConstrains.Aggregate(driver.FindElement(firstConstraint), NextElement);
        }

        public static IWebElement FindElement(this IWebElement element, string cssSelector)
        {
            var constraints = GetConstraints(cssSelector);
            var firstConstraint = constraints.First();
            var restOfTheConstrains = constraints.Skip(1);
            return restOfTheConstrains.Aggregate(element.FindElement(firstConstraint), NextElement);
        }

        private static IWebElement NextElement(IWebElement element, By constraint)
        {
            return element.FindElement(constraint);
        }
        
        private static IEnumerable<By> GetConstraints(string cssSelector)
        {
            return cssSelector.ToCssSelectors().Select(selector => ToSeleniumConstraint(selector));
        }

        public static By ToSeleniumConstraint(CssSelectors selector)
        {
            var constraintMapping = seleniumConstraints.First(c => c.Key(selector).Matches());
            return constraintMapping.Value(constraintMapping.Key(selector).ToString());
        }
    }
}